package models

import (
	"errors"
	"strings"

	"gitee.com/sansaniot/ssiot-core/httpmvc/model"
	"gorm.io/datatypes"

	cDto "ssdevice/common/dto"
	"ssdevice/common/utils"
	"ssdevice/internal/device/models/query"
)

type SysDevConfig struct {
	Id           string          `json:"id" gorm:"primaryKey;type:varchar(255);comment:id"`
	DevSn        string          `json:"devSn" gorm:"type:varchar(255);comment:设备序列号"`
	Data         datatypes.JSON  `json:"data" gorm:"type:jsonb;comment:profile.config"`
	CreateTime   *cDto.LocalTime `json:"createTime" gorm:"type:timestamptz(6);comment:创建时间"`
	UpdateTime   *cDto.LocalTime `json:"updateTime" gorm:"type:timestamptz(6);comment:更新时间"`
	ProductModel string          `json:"productModel" gorm:"type:varchar(255);comment:产品编码"`
	DevProductId string          `json:"devProductId" gorm:"type:varchar(255);comment:产品Id"`

	model.Model
}

func (SysDevConfig) TableName() string {
	return "sys_dev_config"
}

func (e *SysDevConfig) Generate() interface{} {
	o := *e
	return &o
}

func (e *SysDevConfig) GetId() interface{} {
	return e.Id
}

func (e *SysDevConfig) FindDevConfig(req *query.SysDevConfigQuery) error {
	return e.FindOne(e, cDto.MakeCondition(req.GetNeedSearch()))
}

func (e *SysDevConfig) FindDevConfigBySn(sn string) error {
	return e.FindOne(e, cDto.MakeCondition(query.SysDevConfigQuery{Sn: sn}))
}
func (e *SysDevConfig) FindDevConfigByPdModel(pdmodel string) error {
	return e.FindOne(e, cDto.MakeCondition(query.SysDevConfigQuery{ProductModel: pdmodel}))
}

func (e *SysDevConfig) GetKeyType(dev *SysDev, key string) (keyType string, err error) {
	queryPath := "config.sensor." + key + ".type"
	if err = e.FindOne(e, cDto.MakeCondition(query.SysDevConfigQuery{Sn: dev.Sn})); err != nil {
		return
	}
	keyTypeObj := utils.GetFieldFromJson(strings.Split(queryPath, "."), utils.BytesToMap(e.Data))
	if keyTypeObj == nil {
		err = errors.New("不存在的变量")
		return
	}
	keyType = strings.ToLower(keyTypeObj.(string))
	if keyType == "array" || keyType == "object" || keyType == "string" {
		//
	} else if keyType == "boolean" || keyType == "bool" {
		keyType = "boolean"
	} else if strings.Contains(keyType, "int") ||
		strings.Contains(keyType, "float") ||
		strings.Contains(keyType, "number") ||
		strings.Contains(keyType, "double") ||
		strings.Contains(keyType, "decimal") ||
		strings.Contains(keyType, "hex") {
		keyType = "number"
	} else {
		err = errors.New("变量类型异常")
	}
	return
}

func (e *SysDevConfig) GetSubDeviceConfig(gateSn string) (result map[string]interface{}, err error) {
	dev := &SysDev{}
	dev.Orm = e.Orm
	devList := make([]SysDev, 0)
	if err = dev.FindList(&devList, cDto.MakeCondition(query.SysDevQuery{GatewaySnIn: []string{gateSn}})); err != nil {
		return
	}
	if len(devList) == 0 {
		return
	}
	deviceSns := make([]string, 0)
	for _, v := range devList {
		deviceSns = append(deviceSns, v.Sn)
	}
	devConfigList := make([]SysDevConfig, 0)
	if err = e.FindList(&devConfigList, cDto.MakeCondition(query.SysDevConfigQuery{SnIn: deviceSns})); err != nil {
		return
	}
	result = make(map[string]interface{})
	for _, v := range devConfigList {
		result[v.DevSn] = utils.GetFieldFromJson([]string{"config"}, utils.BytesToMap(v.Data))
	}
	return
}
